home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- pdat.c - Support for file read/write of glo_object/PolyData structure.
-
- Tim Heidmann, Silicon Graphics
- June 26, 1991
- */
- #include <stdio.h>
- #include "glo_obj.h"
- #include "shadows.h"
- #include "vect.h"
-
- #define MAXEDGES 10000
- #define MAXFACES 10000
-
- Boolean
- ReadPDataObj(char *filename, glo_ObjPtr *drawlistp, PolyDataPtr *datalistp) {
- /* Try to read a binary drawlist & datalist object file.
- Return TRUE on success. */
- FILE *inf;
- glo_ObjPtr drawlist;
- PolyDataPtr datalist;
- int nList, nTrip, nListBytes, nTripBytes, version;
- int nEdgesBytes, nFacesBytes;
- char buf[20];
-
- /* Open the file for reading and check the file type. */
- if ((inf = fopen(filename, "r")) == NULL ||
- fread(buf, 1, 8, inf) < 8 ||
- strncmp(buf, "pdataobj", 8) != 0) return FALSE;
- if (fread(&version, 1, sizeof(int), inf) < sizeof(int)) return FALSE;
-
- /* Allocate and read drawlist and triplets */
- drawlist = (glo_ObjPtr) malloc(sizeof(glo_ObjTyp));
- if (fread(&nList, 1, sizeof(int), inf) < sizeof(int)) return FALSE;
- nListBytes = nList * sizeof(int);
- drawlist->list = (int *) malloc(nListBytes);
- if (fread(&nTrip, 1, sizeof(int), inf) < sizeof(int)) return FALSE;
- nTripBytes = nTrip * 3 * sizeof(float);
- drawlist->t = (float **) malloc(nTripBytes);
- if (fread(drawlist->list, 1, nListBytes, inf) < nListBytes) return FALSE;
- if (fread(drawlist->t, 1, nTripBytes, inf) < nTripBytes) return FALSE;
-
- /* Allocate and read face and edge lists */
- datalist = (PolyDataPtr) malloc(sizeof(PolyDataRec));
- if (fread(&datalist->nFaces, 1, sizeof(int), inf) < sizeof(int))
- return FALSE;
- nFacesBytes = datalist->nFaces * sizeof(FaceRec);
- datalist->faces = (FacePtr) malloc(nFacesBytes);
- if (fread(&datalist->nEdges, 1, sizeof(int), inf) < sizeof(int))
- return FALSE;
- nEdgesBytes = datalist->nEdges * sizeof(EdgeRec);
- datalist->edges = (EdgePtr) malloc(nEdgesBytes);
-
- if (fread(datalist->faces, 1, nFacesBytes, inf) < nFacesBytes) return FALSE;
- if (fread(datalist->edges, 1, nEdgesBytes, inf) < nEdgesBytes) return FALSE;
-
- if (fclose(inf) != 0) return FALSE;
- *drawlistp = drawlist;
- *datalistp = datalist;
- return TRUE;
- }
-
-
- Boolean
- WritePDataObj(char *filename, glo_ObjPtr drawlist, PolyDataPtr datalist) {
- FILE *outf;
- int version, nTrip, nList;
-
- /* Open the file for writing and write type and version number */
- if ((outf = fopen(filename, "w")) == NULL) return FALSE;
- fwrite("pdataobj", 1, 8, outf);
- version = 1;
- fwrite(&version, 1, sizeof(int), outf);
-
- /* Write the glo_object list and triplets */
- glo_GetLengths(drawlist, &nList, &nTrip);
- fwrite(&nList, 1, sizeof(int), outf);
- fwrite(&nTrip, 1, sizeof(int), outf);
- fwrite(drawlist->list, 1, nList * sizeof(int), outf);
- fwrite(drawlist->t, 1, nTrip * 3 * sizeof(float), outf);
-
- /* Write the pdata face and edge info */
- fwrite(&datalist->nFaces, 1, sizeof(int), outf);
- fwrite(&datalist->nEdges, 1, sizeof(int), outf);
- fwrite(datalist->faces, 1, datalist->nFaces * sizeof(FaceRec), outf);
- fwrite(datalist->edges, 1, datalist->nEdges * sizeof(EdgeRec), outf);
-
- fclose(outf);
- return TRUE;
- }
-
-
- void
- AddEdge(EdgePtr edgeList, int *nEdgesp, int v1, int v2, int thisFace,
- int *iEdgep, int *iSidep)
- {
- /* Add an instance of this edge to list. Set face, and vertices if
- this is the first occurence of this edge. Don't set next recs.
- Return resulting edge index and side in iEdgep, *iSidep. */
- int iEdge, iSide, thisEdge;
-
- for (iEdge = 0; iEdge < *nEdgesp; iEdge++) {
- /* Check for this edge exists already */
- for (iSide=0; iSide<2; iSide++)
- if (edgeList[iEdge].e[iSide].face >= 0 &&
- edgeList[iEdge].e[iSide].vertex == v1 &&
- edgeList[iEdge].e[1-iSide].vertex == v2) {
- *iEdgep = iEdge;
- *iSidep = iSide;
- goto AddNew;
- }
-
- /* Check for this edge in the opposite direction */
- if (edgeList[iEdge].e[0].face >= 0 &&
- edgeList[iEdge].e[0].vertex == v2 &&
- edgeList[iEdge].e[1].vertex == v1) {
- edgeList[iEdge].e[1].face = thisFace;
- *iEdgep = iEdge;
- *iSidep = 1;
- return;
- }
- }
-
- /* Need to add a new edge. */
- AddNew:
- edgeList[*nEdgesp].e[0].face = thisFace;
- edgeList[*nEdgesp].e[1].face = -1;
- edgeList[*nEdgesp].e[0].vertex = v1;
- edgeList[*nEdgesp].e[1].vertex = v2;
- *iEdgep = *nEdgesp;
- *iSidep = 0;
- (*nEdgesp)++;
- }
-
-
- PolyDataPtr
- GetPolyData(glo_ObjPtr pdl)
- {
- /* Compile a list of all edges - their vertices and adjoining faces.
- Assume no degenerate edges or polygons.
- Rules for edge list data structure:
- - edges go in a counterclockwise direction.
- - face is the polygon on the left side of the edge.
- - this side's vertex is the first vertex, other sides is the second.
- - face element value <0 means that side of the edge unused.
- - nextEdge/nextSide point at next edge reference in this direction
- around the polygon.
- */
- int nEdges, nFaces;
- FaceRec faceList[MAXFACES];
- EdgeRec edgeList[MAXEDGES];
- int i, lastv, firstv, *lip, thisFace, thisEdge, thisSide;
- int lastEdge, lastSide, firstEdge, firstSide;
- PolyDataPtr myPDP;
- Boolean done;
- enum {nonorm, nperv, nperp} mode;
- float edge1[3], edge2[3];
-
- nEdges = 0;
- nFaces = 0;
-
- mode = nonorm;
- lip = pdl->list;
- for (done = FALSE; !done;) {
- switch (*lip) {
- case NONORM: mode = nonorm; break;
- case NPERV: mode = nperv; break;
- case NPERP: mode = nperp; break;
- case ENDLIST: done = TRUE; break;
- case BGNPOLY:
- /* Add a poly face record - first, get the normal */
- lip++;
- thisFace = nFaces++;
- switch(mode) {
- case nonorm:
- /* No normals. Need to compute one */
- vsub(pdl->t[lip[1]], pdl->t[lip[0]], edge1);
- vsub(pdl->t[lip[2]], pdl->t[lip[1]], edge2);
- vcross(edge1, edge2, faceList[thisFace].n);
- vnormal(faceList[thisFace].n);
- break;
- case nperv:
- /* Normal per vertex. Still need to get face normal */
- /* Skip over normals when calculating edge vectors */
- vsub(pdl->t[lip[3]], pdl->t[lip[1]], edge1);
- vsub(pdl->t[lip[5]], pdl->t[lip[3]], edge2);
- vcross(edge1, edge2, faceList[thisFace].n);
- vnormal(faceList[thisFace].n);
- break;
- case nperp:
- /* Normal per polygon; just copy the normal */
- vcopy(pdl->t[lip[0]], faceList[thisFace].n);
- break;
- }
-
- /* then, add each edge of this poly to the master edge list. */
- /* Get the first vertex. */
- lip += (mode == nonorm) ? 0 : 1;
- firstv = *lip;
-
- /* Get the next vertex and add the first edge */
- lip += (mode == nperv) ? 2 : 1;
- AddEdge(edgeList, &nEdges, firstv, *lip, thisFace,
- &firstEdge, &firstSide);
- lastv = *lip;
- lastEdge = firstEdge;
- lastSide = firstSide;
-
- /* While there is another vertex, add an edge to the list */
- while (lip[1] >= 0) {
- /* Get the next vertex, skipping normals */
- lip += (mode == nperv) ? 2 : 1;
-
- /* Add an edge and link the last edge to it */
- AddEdge(edgeList, &nEdges, lastv, *lip, thisFace,
- &thisEdge, &thisSide);
- edgeList[lastEdge].e[lastSide].nextEdge = thisEdge;
- edgeList[lastEdge].e[lastSide].nextSide = thisSide;
-
- lastv = *lip;
- lastEdge = thisEdge;
- lastSide = thisSide;
- }
-
- /* Add the final edge to the edge list, link backward & forward */
- AddEdge(edgeList, &nEdges, lastv, firstv, thisFace,
- &thisEdge, &thisSide);
- edgeList[lastEdge].e[lastSide].nextEdge = thisEdge;
- edgeList[lastEdge].e[lastSide].nextSide = thisSide;
- edgeList[thisEdge].e[thisSide].nextEdge = firstEdge;
- edgeList[thisEdge].e[thisSide].nextSide = firstSide;
-
- break;
-
- default: ;
- }
-
- /* Consider the next list item */
- lip++;
- }
-
- /* Allocate and set up a poly data record */
- myPDP = (PolyDataPtr) malloc(sizeof(PolyDataRec));
- myPDP->nEdges = nEdges;
- myPDP->nFaces = nFaces;
- myPDP->faces = (FacePtr) malloc(nFaces * sizeof(FaceRec));
- for (i = 0; i < nFaces; i++) myPDP->faces[i] = faceList[i];
- myPDP->edges = (EdgePtr) malloc(nEdges * sizeof(EdgeRec));
- for (i = 0; i < nEdges; i++) myPDP->edges[i] = edgeList[i];
-
- return myPDP;
- }
-
-